package com.clementheliou.cheliou.dal.dao.generic;

import com.clementheliou.cheliou.dal.dao.base.BaseDAO;
import com.clementheliou.cheliou.dal.model.base.BaseEntity;

/**
 * This interface declares common parameterized methods of application DAO's. Methods that don't
 * make use of generic types should be declared in the {@link BaseDAO} interface.
 * 
 * @author Clément HELIOU (clement.heliou@gmail.com)
 * @param <T> the parameterized type. It must extend {@link BaseEntity}.
 * @see {@link BaseDAO};
 * @see {@link BaseEntity}.
 * @since 1.0
 */
public interface GenericDAO<T extends BaseEntity> extends BaseDAO {

	/**
	 * Gets the total number of entities.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @return the resulting number of entities.
	 * @since 1.0
	 */
	Integer count();

	/**
	 * Removes a persistent instance from the datastore. The argument may be an instance associated
	 * with the receiving <tt>Session</tt> or a transient instance with an identifier associated
	 * with existing persistent state. This operation cascades to associated instances if the
	 * association is mapped with {@code cascade="delete"}.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @param entity the <code>T</code> instance to be removed
	 * @since 1.0
	 */
	void deleteEntity(T entity);

	/**
	 * Returns the persistent instance of the <code>T</code> class with the given identifier, or
	 * null if there is no such persistent instance. If the instance is already associated with the
	 * session, return that instance. This method never returns an uninitialized instance.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @param id an identifier.
	 * @return a persistent instance or <code>null</code>.
	 * @since 1.0
	 */
	T getEntity(Integer id);

	/**
	 * <p>
	 * Returns the persistent instance of the <code>T</code> class with the given identifier,
	 * assuming that the instance exists. This method might return a proxied instance that is
	 * initialized on-demand, when a non-identifier method is accessed.
	 * </p>
	 * <p>
	 * You should not use this method to determine if an instance exists (use <code>get()</code>
	 * instead). Use this only to retrieve an instance that you assume exists, where non-existence
	 * would be an actual error.
	 * </p>
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @param id a valid identifier of an existing persistent instance of the <code>T</code> class.
	 * @return the persistent instance or proxy.
	 * @since 1.0
	 */
	T loadEntity(Integer id);

	/**
	 * <p>
	 * Copies the state of the given object onto the persistent object with the same identifier. If
	 * there is no persistent instance currently associated with the session, it will be loaded.
	 * Returns the persistent instance. If the given instance is unsaved, save a copy of and return
	 * it as a newly persistent instance. The given instance does not become associated with the
	 * session. This operation cascades to associated instances if the association is mapped with
	 * cascade="merge".
	 * </p>
	 * <p>
	 * The semantics of this method are defined by JSR-220.
	 * </p>
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @param entity the entity to manage.
	 * @return the attached entity.
	 * @since 1.0
	 */
	T mergeEntity(T entity);

	/**
	 * Persists the given transient <code>T</code> instance, first assigning a generated identifier
	 * (or using the current value of the identifier property if the <tt>assigned</tt> generator is
	 * used). This operation cascades to associated instances if the association is mapped with
	 * {@code cascade="save-update"}.
	 * 
	 * @author Clément HELIOU (clement.heliou@gmail.com)
	 * @param object a transient instance of <code>T</code> class.
	 * @return the generated identifier.
	 * @since 1.0
	 */
	Integer saveEntity(T entity);
}
